package ge.telasi.tasks.model;

import ge.telasi.tasks.LocaleManager;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 * @author dimitri
 */
@Entity
@Table(name = "tasks")
public class Task extends Modifiable {
    private static final long serialVersionUID = 1871452301234184267L;

    public static String getStatusName(LocaleManager lm, int status) {
        switch (status) {
            case Task.STATUS_DRAFT:
                return lm.getMessage("Task.Status.Draft");
            case Task.STATUS_OPEN:
                return lm.getMessage("Task.Status.Open");
            case Task.STATUS_PAUSED:
                return lm.getMessage("Task.Status.Paused");
            case Task.STATUS_COMPLETE_OK:
                return lm.getMessage("Task.Status.Complete");
            case Task.STATUS_COMPLETE_CANCEL:
                return lm.getMessage("Task.Status.Complete.Canceled");
            case Task.STATUS_CLOSED_OK:
                return lm.getMessage("Task.Status.Closed");
            case Task.STATUS_CLOSED_CANCEL:
                return lm.getMessage("Task.Status.Closed.Canceled");
            default:
                return "?";
        }
    }

    public static final int STATUS_DRAFT = -1;
    public static final int STATUS_OPEN = 0;
    public static final int STATUS_PAUSED = 1;
    public static final int STATUS_COMPLETE_OK = 2;
    public static final int STATUS_COMPLETE_CANCEL = 3;
    public static final int STATUS_CLOSED_OK = 4;
    public static final int STATUS_CLOSED_CANCEL = 5;

    public static final int PRIORITY_LOW = -1;
    public static final int PRIORITY_NORMAL = 0;
    public static final int PRIORITY_HIGH = 1;

    public static final String ROLE_OWNER = "owner";
    public static final String ROLE_PREPARED_BY = "prepared_by";
    public static final String ROLE_ASSIGNEE = "assignee";
    public static final String ROLE_CARBON_COPY = "copy";
    public static final String ROLE_FILE_OWNER = "file_owner";

    public static final int TYPE_GENERAL = 1;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TASKS_SEQ")
    @SequenceGenerator(name = "TASKS_SEQ", sequenceName = "TASKS_SEQ", allocationSize = 1)
    private Long id;
    @ManyToOne
    @JoinColumn(name = "owner_id")
    private User owner;
    @ManyToOne
    @JoinColumn(name = "prepared_by")
    private User preparedBy;
    @Column(name = "task_number")
    private String number;
    @Column(name = "subject")
    private String subject;
    @ManyToOne
    @JoinColumn(name = "structure_id")
    private Structure structure;
    @Column(name = "last_body")
    private String lastBody;
    @OneToMany(mappedBy = "task")
    private List<TaskReceiver> receivers = new ArrayList<TaskReceiver>();
    @OneToMany(mappedBy = "task")
    @OrderBy("id ASC")
    private List<TaskBody> bodies = new ArrayList<TaskBody>();
    @Column(name = "task_status")
    private int taskStatus;
    @Column(name = "priority_id")
    private int priority;
    @Column(name = "due_date")
    @Temporal(value = TemporalType.DATE)
    private Calendar dueDate;
    @Column(name = "task_type")
    private int type;
    @OneToMany(mappedBy="task")
    private List<TaskAttachment> attachments = new ArrayList<TaskAttachment>();
    @OneToMany(mappedBy = "child")
    private List<TaskRelation> parents = new ArrayList<TaskRelation>();
    @OneToMany(mappedBy = "parent")
    private List<TaskRelation> children = new ArrayList<TaskRelation>();
    @Column(name = "has_attachment")
    private int attachmentBit;
    @Column(name = "has_parent")
    private int parentBit;
    @Column(name = "has_child")
    private int childBit;
    @Column(name = "canc_number")
    private String cancelariaNumber;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public boolean isDraft() {
        return taskStatus == STATUS_DRAFT;
    }

    public User getOwner() {
        return owner;
    }

    public void setOwner(User owner) {
        this.owner = owner;
    }

    public User getPreparedBy() {
        return preparedBy;
    }

    public void setPreparedBy(User preparedBy) {
        this.preparedBy = preparedBy;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public Structure getStructure() {
        return structure;
    }

    public void setStructure(Structure structure) {
        this.structure = structure;
    }

    public String getLastBody() {
        return lastBody;
    }

    public void setLastBody(String lastBody) {
        this.lastBody = lastBody;
    }

    public List<TaskReceiver> getReceivers() {
        return receivers;
    }

    public void setReceivers(List<TaskReceiver> receivers) {
        this.receivers = receivers;
    }

    public List<TaskBody> getBodies() {
        return bodies;
    }

    public void setBodies(List<TaskBody> bodies) {
        this.bodies = bodies;
    }

    public int getTaskStatus() {
        return taskStatus;
    }

    public void setTaskStatus(int taskStatus) {
        this.taskStatus = taskStatus;
    }

    public int getPriority() {
        return priority;
    }

    public void setPriority(int priority) {
        this.priority = priority;
    }

    public Calendar getDueDate() {
        return dueDate;
    }

    public void setDueDate(Calendar dueDate) {
        this.dueDate = dueDate;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public List<TaskAttachment> getAttachments() {
        return attachments;
    }

    public void setAttachments(List<TaskAttachment> attachments) {
        this.attachments = attachments;
    }

    public List<TaskRelation> getParents() {
        return parents;
    }

    public void setParents(List<TaskRelation> parents) {
        this.parents = parents;
    }

    public String getCancelariaNumber() {
        return cancelariaNumber;
    }

    public void setCancelariaNumber(String cancelariaNumber) {
        this.cancelariaNumber = cancelariaNumber;
    }

    public List<TaskRelation> getChildren() {
        return children;
    }

    public void setChildren(List<TaskRelation> children) {
        this.children = children;
    }

    public boolean hasAttachment() {
        return attachmentBit == 1;
    }

    public void setHasAttachment(boolean hasAttachment) {
        this.attachmentBit = hasAttachment ? 1 : 0;
    }

    public boolean hasParent() {
        return parentBit == 1;
    }

    public void setHasParent(boolean hasParent) {
        this.parentBit = hasParent ? 1 : 0;
    }

    public boolean hasChild() {
        return childBit == 1;
    }

    public void setHasChild(boolean hasChild) {
        this.childBit = hasChild ? 1 : 0;
    }

    public void addAttachment(TaskAttachment attachment) {
        attachments.add(attachment);
        setHasAttachment(!attachments.isEmpty());
    }

    public void removeAttachment(TaskAttachment attachment) {
        attachments.remove(attachment);
        setHasAttachment(!attachments.isEmpty());
    }

    public void addParent(TaskRelation relation) {
        parents.add(relation);
        setHasParent(!parents.isEmpty());
    }

    public void removeParent(TaskRelation relation) {
        parents.remove(relation);
        setHasParent(!parents.isEmpty());
    }

    public void addChild(TaskRelation relation) {
        children.add(relation);
        setHasChild(!children.isEmpty());
    }

    public void removeChild(TaskRelation relation) {
        children.remove(relation);
        setHasChild(!children.isEmpty());
    }

    public List<TaskReceiver> getAssignees() {
        List<TaskReceiver> assignees = new ArrayList<TaskReceiver>();
        for (TaskReceiver receiver : receivers) {
            if (!receiver.isCopy()) {
                assignees.add(receiver);
            }
        }
        return assignees;
    }

    public List<TaskReceiver> getCopies() {
        List<TaskReceiver> copies = new ArrayList<TaskReceiver>();
        for (TaskReceiver receiver : receivers) {
            if (receiver.isCopy()) {
                copies.add(receiver);
            }
        }
        return copies;
    }

    @Override
    public boolean equals(Object obj) {
        if (id == null) {
            return false;
        }
        if (obj instanceof Task) {
            Task task = (Task) obj;
            return id.equals(task.getId());
        }
        return false;
    }

    @Override
    public int hashCode() {
        return id != null ? id.hashCode() : 0;
    }

}
